﻿using System;
using System.Collections.Generic;

namespace PacketRush.Core
{
    /// <summary>
    /// Base class for shared functionality between
    /// <see cref="PacketRush.Core.NetServer"/> and <see cref="PacketRush.Core.NetClient"/>.
    /// </summary>
    public abstract class NetBase
    {

        /// <summary>
        /// Occurs when a socket error is raised.
        /// </summary>
        public event EventHandler<NetErrorEventArgs> Error;

        /// <summary>
        /// Raises the <see cref="PacketRush.Core.NetBase.Error"/> event.
        /// </summary>
        protected virtual void OnError(NetErrorEventArgs args)
        {
            if (Error != null)
            {
                Error(this, args);
            }
        }

        private List<INetService> _Services = new List<INetService>();
        /// <summary>
        /// A list of registered services.
        /// </summary>
        /// <remarks>
        /// Used by <see cref="PacketRush.Core.NetServer"/> and <see cref="PacketRush.Core.NetClient"/> to
        /// manage registered services.
        /// </remarks>
        protected List<INetService> Services
        {
            get
            {
                return _Services;
            }
        }
        /// <summary>
        /// Register a service.
        /// </summary>
        /// <param name="service">The service to register.</param>
        /// <returns>The service index</returns>
        public int RegisterService(INetService service)
        {
            Services.Add(service);

            return Services.Count - 1;
        }

        /// <summary>
        /// Gets a registered service by its service index.
        /// </summary>
        /// <param name="serviceIndex">The service index.</param>
        /// <returns>The service.</returns>
        public INetService GetService(int serviceIndex)
        {
            if (serviceIndex < Services.Count)
            {
                return Services[serviceIndex];
            }

            return null;
        }

        /// <summary>
        /// Deliver a packet to its designated service.
        /// </summary>
        /// <param name="packet">The packet.</param>
        protected void DeliverPacketToService(Packet packet)
        {
            if (packet.ServiceId >= Services.Count) throw new InvalidProgramException("Invalid service index. An attempt was made to deliver a packet to an invalid service.");

            if (packet.ServiceId > -1)
            {
                Services[packet.ServiceId].DeliverPacket(packet);
            }
            else
            {
                ProcessSystemPacket(packet);
            }
        }

        /// <summary>
        /// Processes packets that are not handled by any service, such as
        /// connection packets.
        /// </summary>
        /// <param name="packet">The packet.</param>
        protected abstract void ProcessSystemPacket(Packet packet);

    }
}
